﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using eXamineBusiness.SystemDescription.Data;
using eXamineBusiness.SystemDescription.Events;
using eXamineBusiness.SystemDescription.Exceptions;

namespace eXamineBusiness.SystemDescription
{
    public abstract class DescriptionItem
    {

        private String _name;

        public DescriptionItem (String name)
        {
            Contract.Requires(name != null);
            Contract.Requires(NameCollection.ValidName(name));
            this._name = name;
        }

        #region Properties
        public String DescriptionText { get; set; }
        public virtual string Name
        {
            get
            {
                return this._name;
            }
            set
            {
                if (!this._name.Equals(value)) {
                    this._name = value;
                    this.OnNameChanged();
                }
            }
        }

        public Description Parent { get; set; }
        public bool HasParent { get { return (!IsRoot && Parent != null); } }
        public Description RootParent { get; set; }
        public bool HasRootParent { get { return this.RootParent != null; } }
        public bool IsRoot
        {
            get { return ReferenceEquals(this, this.RootParent); }
        }
        public String UniqueName
        {
            get
            {
                return this.GetUniqueName(this.Name);
            }
        } 
        #endregion

        #region Auxiliar
        private String GetUniqueName (String local)
        {
            Contract.Requires(local != null);
            Contract.Ensures(Contract.Result<String>().EndsWith(local));
            if (this.IsRoot || !this.HasParent) return local;
            else return this.Parent.UniqueName + "." + local;
        }
        #endregion

        #region API
        public bool DeepEquals (DescriptionItem item)
        {
            Contract.Requires(item != null);
            return this.UniqueName.Equals(item.UniqueName);
        }
        #endregion

        #region Override
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj is DescriptionItem) return this.DeepEquals((DescriptionItem)obj);
            if (obj is String) return this.Equals((String)obj);
            return false;
        }

        private bool Equals(String str)
        {
            Contract.Requires(str != null);
            return this.Name.Equals(str);
        }
        #endregion

        #region Events
        public event EventHandler<NameChangedEventArgs> NameChanged;
        public void OnNameChanged ()
        {
            if (this.NameChanged != null)
            {
                this.NameChanged.Invoke(this, new NameChangedEventArgs(Name));
            }
        }
        public event EventHandler ItemRemoved;
        public void SignalAsRemoved()
        {
            if (this.ItemRemoved != null)
                this.ItemRemoved.Invoke(this, new EventArgs());
        }
        #endregion

    }
}
